<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="theme-color" content="#0078E7"><meta name="author" content="爱肖彤真是太好了"><meta name="copyright" content="爱肖彤真是太好了"><meta name="generator" content="Hexo 5.1.1"><meta name="theme" content="hexo-theme-yun"><title>支付宝网页支付接口调用 | 工藤旧二の博客</title><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@900&amp;display=swap" media="none" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/star-markdown-css@0.1.19/dist/yun/yun-markdown.min.css"><script src="//at.alicdn.com/t/font_1140697_stqaphw3j4.js" async></script><script src="https://cdn.jsdelivr.net/npm/scrollreveal/dist/scrollreveal.min.js" defer></script><script>document.addEventListener("DOMContentLoaded", () => {
  [".post-card",".post-content img"].forEach((target)=> {
    ScrollReveal().reveal(target);
  })
});
</script><link rel="shortcut icon" type="image/svg+xml" href="/task/yun.ico"><link rel="mask-icon" href="/task/yun.ico" color="#0078E7"><link rel="alternate icon" href="/yun.ico"><link rel="preload" href="/task/css/hexo-theme-yun.css" as="style"><link rel="preload" href="/task/js/utils.js" as="script"><link rel="preload" href="/task/js/hexo-theme-yun.js" as="script"><link rel="prefetch" href="/task/js/sidebar.js" as="script"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><link rel="stylesheet" href="/task/css/hexo-theme-yun.css"><link rel="alternate" href="/task/atom.xml" title="工藤旧二の博客" type="application/atom+xml"><script id="yun-config">
    const Yun = window.Yun || {};
    window.CONFIG = {"root":"/task/","title":"工藤旧二の博客","version":"0.9.7","anonymous_image":"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg","say":{"api":"https://v1.hitokoto.cn","hitokoto":true},"local_search":{"path":"/task/search.xml"},"fireworks":{"colors":["102, 167, 221","62, 131, 225","33, 78, 194"]}};
  </script><script>(function(){
  var bp = document.createElement('script');
  var curProtocol = window.location.protocol.split(':')[0];
  if (curProtocol === 'https') {
    bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
  }
  else {
    bp.src = 'http://push.zhanzhang.baidu.com/push.js';
  }
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(bp, s);
})();</script><meta name="description" content="一、SDK&#x2F;API接口的调用支付宝平台不提供python的sdk，只有api，我们可以去网上找别人封装好的sdk，复制过来，了解对应参数 可以通过支付宝提供的软件自动生成公钥和私钥 from alipay import AliPay   # app_private_key_string &#x3D; open(&quot;&#x2F;path&#x2F;to&#x2F;your&#x2F;private&#x2F;key.pem&quot;).read() # alipay_">
<meta property="og:type" content="article">
<meta property="og:title" content="支付宝网页支付接口调用">
<meta property="og:url" content="http://huang_zhao.gitee.io/task/2020/04/25/python/%E6%A8%A1%E5%9D%97/%E6%94%AF%E4%BB%98%E5%AE%9D%E7%BD%91%E9%A1%B5%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8/index.html">
<meta property="og:site_name" content="工藤旧二の博客">
<meta property="og:description" content="一、SDK&#x2F;API接口的调用支付宝平台不提供python的sdk，只有api，我们可以去网上找别人封装好的sdk，复制过来，了解对应参数 可以通过支付宝提供的软件自动生成公钥和私钥 from alipay import AliPay   # app_private_key_string &#x3D; open(&quot;&#x2F;path&#x2F;to&#x2F;your&#x2F;private&#x2F;key.pem&quot;).read() # alipay_">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2020-04-25T05:20:11.000Z">
<meta property="article:modified_time" content="2020-08-26T01:05:37.000Z">
<meta property="article:author" content="爱肖彤真是太好了">
<meta property="article:tag" content="django">
<meta property="article:tag" content="python">
<meta property="article:tag" content="第三方接口">
<meta name="twitter:card" content="summary"><script src="/task/js/ui/mode.js"></script><link rel="stylesheet" href="/task/css/prism.css" type="text/css"></head><body><script defer src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script defer src="/task/js/ui/fireworks.js"></script><canvas class="fireworks"></canvas><div class="container"><a class="sidebar-toggle hty-icon-button" id="menu-btn"><div class="hamburger hamburger--spin" type="button"><span class="hamburger-box"><span class="hamburger-inner"></span></span></div></a><div class="sidebar-toggle sidebar-overlay"></div><aside class="sidebar"><script src="/task/js/sidebar.js"></script><ul class="sidebar-nav"><li class="sidebar-nav-item sidebar-nav-toc hty-icon-button sidebar-nav-active" data-target="post-toc-wrap" title="文章目录"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-list-ordered"></use></svg></li><li class="sidebar-nav-item sidebar-nav-overview hty-icon-button" data-target="site-overview-wrap" title="站点概览"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-passport-line"></use></svg></li></ul><div class="sidebar-panel" id="site-overview-wrap"><div class="site-info fix-top"><a class="site-author-avatar" href="/task/about/" title="爱肖彤真是太好了"><img width="96" loading="lazy" src="/task/Yun.png" alt="爱肖彤真是太好了"></a><div class="site-author-name"><a href="/task/about/">爱肖彤真是太好了</a></div><a class="site-name" href="/task/about/site.html">工藤旧二の博客</a><sub class="site-subtitle"></sub><div class="site-desciption"></div></div><nav class="site-state"><a class="site-state-item hty-icon-button icon-home" href="/task/" title="首页"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-home-4-line"></use></svg></span></a><div class="site-state-item"><a href="/task/archives/" title="归档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-archive-line"></use></svg></span><span class="site-state-item-count">57</span></a></div><div class="site-state-item"><a href="/task/categories/" title="分类"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-2-line"></use></svg></span><span class="site-state-item-count">2</span></a></div><div class="site-state-item"><a href="/task/tags/" title="标签"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="site-state-item-count">50</span></a></div><a class="site-state-item hty-icon-button" target="_blank" rel="noopener" href="https://yun.yunyoujun.cn" title="文档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-settings-line"></use></svg></span></a></nav><hr style="margin-bottom:0.5rem"><div class="links-of-author"><a class="links-of-author-item hty-icon-button" rel="noopener" title="RSS" target="_blank" style="color:orange"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-rss-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="QQ" target="_blank" style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="GitHub" target="_blank" style="color:#6e5494"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-github-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="微博" target="_blank" style="color:#E6162D"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-weibo-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="豆瓣" target="_blank" style="color:#007722"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-douban-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://music.163.com/#/user/home?id=552858287" title="网易云音乐" target="_blank" style="color:#C20C0C"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-netease-cloud-music-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="知乎" target="_blank" style="color:#0084FF"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-zhihu-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://space.bilibili.com/15081363" title="哔哩哔哩" target="_blank" style="color:#FF8EB3"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-bilibili-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Twitter" target="_blank" style="color:#1da1f2"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-twitter-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Telegram Channel" target="_blank" style="color:#0088CC"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-telegram-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="E-Mail" target="_blank" style="color:#8E71C1"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-mail-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Travelling" target="_blank" style="color:var(--hty-text-color)"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-send-plane-2-line"></use></svg></a></div><hr style="margin:0.5rem 1rem"><div class="links"><a class="links-item hty-icon-button" href="/task/links/" title="我的小伙伴们" style="color:dodgerblue"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-genderless-line"></use></svg></a></div><br><a class="links-item hty-icon-button" id="toggle-mode-btn" href="javascript:;" title="Mode" style="color: #f1cb64"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-contrast-2-line"></use></svg></a></div><div class="sidebar-panel sidebar-panel-active" id="post-toc-wrap"><div class="post-toc"><div class="post-toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81SDK-API%E6%8E%A5%E5%8F%A3%E7%9A%84%E8%B0%83%E7%94%A8"><span class="toc-text">一、SDK&#x2F;API接口的调用</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E9%A1%B9%E7%9B%AE%E4%B8%AD%E8%B0%83%E7%94%A8%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3"><span class="toc-text">二、项目中调用支付接口</span></a></li></ol></div></div></div></aside><main class="sidebar-translate" id="content"><div id="post"><article class="post-block" itemscope itemtype="https://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://huang_zhao.gitee.io/task/task/2020/04/25/python/%E6%A8%A1%E5%9D%97/%E6%94%AF%E4%BB%98%E5%AE%9D%E7%BD%91%E9%A1%B5%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8/"><span hidden itemprop="author" itemscope itemtype="https://schema.org/Person"><meta itemprop="name" content="爱肖彤真是太好了"><meta itemprop="description"></span><span hidden itemprop="publisher" itemscope itemtype="https://schema.org/Organization"><meta itemprop="name" content="工藤旧二の博客"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">支付宝网页支付接口调用</h1><div class="post-meta"><div class="post-time" style="display:block"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-line"></use></svg></span> <time title="创建时间：2020-04-25 13:20:11" itemprop="dateCreated datePublished" datetime="2020-04-25T13:20:11+08:00">2020-04-25</time><span class="post-meta-divider">-</span><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-2-line"></use></svg></span> <time title="修改时间：2020-08-26 09:05:37" itemprop="dateModified" datetime="2020-08-26T09:05:37+08:00">2020-08-26</time></div><span class="post-count"><span class="post-symbolcount"><span class="post-meta-item-icon" title="本文字数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-file-word-line"></use></svg></span> <span title="本文字数">1.1k</span><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读时长"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-timer-line"></use></svg></span> <span title="阅读时长">5m</span></span></span><span class="post-busuanzi"><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读次数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg> <span id="busuanzi_value_page_pv"></span></span></span><div class="post-classify"><span class="post-category"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-line"></use></svg></span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a class="category" href="/task/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/" style="--text-color:var(--hty-text-color)" itemprop="url" rel="index"><span itemprop="text">技术分享</span></a></span></span><span class="post-tag"><span class="post-meta-divider">-</span><a class="tag" href="/task/tags/django/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">django</span></a><a class="tag" href="/task/tags/python/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">python</span></a><a class="tag" href="/task/tags/%E7%AC%AC%E4%B8%89%E6%96%B9%E6%8E%A5%E5%8F%A3/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">第三方接口</span></a></span></div></div></header><section class="post-body" itemprop="articleBody"><div class="post-content markdown-body" style="--smc-primary:#0078E7;"><h2 id="一、SDK-API接口的调用"><a href="#一、SDK-API接口的调用" class="headerlink" title="一、SDK/API接口的调用"></a>一、SDK/API接口的调用</h2><p>支付宝平台不提供python的sdk，只有api，我们可以去网上找别人封装好的sdk，复制过来，了解对应参数</p>
<p>可以通过支付宝提供的软件自动生成公钥和私钥</p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">from</span> alipay <span class="token keyword">import</span> AliPay


<span class="token comment" spellcheck="true"># app_private_key_string = open("/path/to/your/private/key.pem").read()</span>
<span class="token comment" spellcheck="true"># alipay_public_key_string = open("/path/to/alipay/public/key.pem").read()</span>

app_private_key_string <span class="token operator">=</span> <span class="token triple-quoted-string string">"""-----BEGIN RSA PRIVATE KEY-----
你的私钥
-----END RSA PRIVATE KEY-----
"""</span>

alipay_public_key_string <span class="token operator">=</span> <span class="token triple-quoted-string string">"""-----BEGIN PUBLIC KEY-----
支付宝平台创建的应用的公钥
-----END PUBLIC KEY-----
"""</span>

alipay <span class="token operator">=</span> AliPay<span class="token punctuation">(</span>
    <span class="token comment" spellcheck="true"># 创建应用的appid</span>
    appid<span class="token operator">=</span><span class="token string">"xxx"</span><span class="token punctuation">,</span>
    app_notify_url<span class="token operator">=</span><span class="token string">'http://127.0.0.1:8000/home/'</span><span class="token punctuation">,</span>  <span class="token comment" spellcheck="true"># the default notify path</span>
    <span class="token comment" spellcheck="true"># 配置你的私钥</span>
    app_private_key_string<span class="token operator">=</span>app_private_key_string<span class="token punctuation">,</span>
    <span class="token comment" spellcheck="true"># alipay public key, do not use your own public key!</span>
    <span class="token comment" spellcheck="true"># 配置应用的公钥</span>
    alipay_public_key_string<span class="token operator">=</span>alipay_public_key_string<span class="token punctuation">,</span>
    <span class="token comment" spellcheck="true"># 加密方式</span>
    sign_type<span class="token operator">=</span><span class="token string">"RSA2"</span><span class="token punctuation">,</span> <span class="token comment" spellcheck="true"># RSA or RSA2</span>
    <span class="token comment" spellcheck="true"># 调试模式，如果用真实环境就要改成True</span>
    debug<span class="token operator">=</span><span class="token boolean">False</span>  <span class="token comment" spellcheck="true"># False by default</span>
<span class="token punctuation">)</span>

<span class="token comment" spellcheck="true"># 支付宝的网关接口</span>
alipay_url<span class="token operator">=</span><span class="token string">'https://openapi.alipaydev.com/gateway.do?'</span>
<span class="token comment" spellcheck="true"># 生成支付页面</span>
order_string <span class="token operator">=</span> alipay<span class="token punctuation">.</span>api_alipay_trade_page_pay    <span class="token punctuation">(</span>
    out_trade_no<span class="token operator">=</span><span class="token string">"20161112www4334"</span><span class="token punctuation">,</span>
    total_amount<span class="token operator">=</span><span class="token number">9999</span><span class="token punctuation">,</span>
    subject<span class="token operator">=</span><span class="token string">'韩红版充气娃娃'</span><span class="token punctuation">,</span> <span class="token comment" spellcheck="true"># 商品名称</span>
    <span class="token comment" spellcheck="true"># 提交get请求的url</span>
    return_url<span class="token operator">=</span><span class="token string">"xxx"</span><span class="token punctuation">,</span>
    <span class="token comment" spellcheck="true"># 提交post请求的url</span>
    notify_url<span class="token operator">=</span><span class="token string">"xxx"</span>
<span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 生成支付链接</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>alipay_url<span class="token operator">+</span>order_string<span class="token punctuation">)</span></code></pre>
<p>这里内部有很多配置信息，可以把配置信息提取出来放到settings文件中，解耦合</p>
<h2 id="二、项目中调用支付接口"><a href="#二、项目中调用支付接口" class="headerlink" title="二、项目中调用支付接口"></a>二、项目中调用支付接口</h2><p>前端点击立即购买，把后端所需要的参数发送给后端</p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">class</span> <span class="token class-name">PayView</span><span class="token punctuation">(</span>GenericViewSet<span class="token punctuation">,</span> CreateModelMixin<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment" spellcheck="true"># 登录jwt认证</span>
    authentication_classes <span class="token operator">=</span> <span class="token punctuation">[</span>JSONWebTokenAuthentication<span class="token punctuation">,</span> <span class="token punctuation">]</span>
    <span class="token comment" spellcheck="true"># 防止游客登录</span>
    permission_classes <span class="token operator">=</span> <span class="token punctuation">[</span>IsAuthenticated<span class="token punctuation">,</span> <span class="token punctuation">]</span>
    queryset <span class="token operator">=</span> models<span class="token punctuation">.</span>Order<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span>
    serializer_class <span class="token operator">=</span> sers<span class="token punctuation">.</span>OrderSerializer

    <span class="token comment" spellcheck="true"># 重写create方法</span>
    <span class="token keyword">def</span> <span class="token function">create</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">,</span> <span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span>
        serializer <span class="token operator">=</span> self<span class="token punctuation">.</span>get_serializer<span class="token punctuation">(</span>data<span class="token operator">=</span>request<span class="token punctuation">.</span>data<span class="token punctuation">,</span> context<span class="token operator">=</span><span class="token punctuation">{</span><span class="token string">'request'</span><span class="token punctuation">:</span> request<span class="token punctuation">}</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 通过序列化类去校验数据，保存数据到数据库，生成支付宝链接</span>
        <span class="token comment" spellcheck="true"># 主要逻辑都在序列化类中</span>
        serializer<span class="token punctuation">.</span>is_valid<span class="token punctuation">(</span>raise_exception<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 等同于ser.save（）</span>
        self<span class="token punctuation">.</span>perform_create<span class="token punctuation">(</span>serializer<span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 返回支付宝支付链接</span>
        <span class="token keyword">return</span> Response<span class="token punctuation">(</span>serializer<span class="token punctuation">.</span>context<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'pay_url'</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<p>序列化类</p>
<pre class=" language-python"><code class="language-python"><span class="token keyword">from</span> rest_framework <span class="token keyword">import</span> serializers
<span class="token keyword">from</span> rest_framework<span class="token punctuation">.</span>exceptions <span class="token keyword">import</span> ValidationError
<span class="token keyword">from</span> django<span class="token punctuation">.</span>conf <span class="token keyword">import</span> settings
<span class="token keyword">from</span> <span class="token punctuation">.</span> <span class="token keyword">import</span> models
<span class="token keyword">class</span> <span class="token class-name">OrderSerializer</span><span class="token punctuation">(</span>serializers<span class="token punctuation">.</span>ModelSerializer<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token comment" spellcheck="true"># 前端传什么数据过来{course:[1,2,3],total_amount:100,subject:xx商品,pay_type:1,}</span>
    <span class="token comment" spellcheck="true"># user字段需要，但是不是传的，使用了jwt</span>


    <span class="token comment" spellcheck="true"># 需要把course:[1,2,3] 处理成 course:[obj1,obj2,obj3]</span>

    <span class="token comment" spellcheck="true"># 课时：[1,4,6,]===>课时：[obj1,obj4,obj6,]</span>
    <span class="token comment" spellcheck="true"># course=serializers.CharField()</span>
    <span class="token keyword">from</span> course<span class="token punctuation">.</span>models <span class="token keyword">import</span> Course
    <span class="token comment" spellcheck="true"># 这个方法可以让课时：[1,4,6,]===>课时：[obj1,obj4,obj6,]</span>
    course<span class="token operator">=</span>serializers<span class="token punctuation">.</span>PrimaryKeyRelatedField<span class="token punctuation">(</span>queryset<span class="token operator">=</span>Course<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>all<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> write_only<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">,</span> many<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>

    <span class="token keyword">class</span> <span class="token class-name">Meta</span><span class="token punctuation">:</span>
        model <span class="token operator">=</span> models<span class="token punctuation">.</span>Order
        fields <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'total_amount'</span><span class="token punctuation">,</span><span class="token string">'subject'</span><span class="token punctuation">,</span><span class="token string">'pay_type'</span><span class="token punctuation">,</span><span class="token string">'course'</span><span class="token punctuation">]</span>
        extra_kwargs<span class="token operator">=</span><span class="token punctuation">{</span>
            <span class="token string">'total_amount'</span><span class="token punctuation">:</span><span class="token punctuation">{</span><span class="token string">'required'</span><span class="token punctuation">:</span><span class="token boolean">True</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
            <span class="token string">'pay_type'</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">'required'</span><span class="token punctuation">:</span> <span class="token boolean">True</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token punctuation">}</span>


    <span class="token keyword">def</span> <span class="token function">_check_price</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>attrs<span class="token punctuation">)</span><span class="token punctuation">:</span>
        total_amount<span class="token operator">=</span>attrs<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'total_amount'</span><span class="token punctuation">)</span>
        course_list<span class="token operator">=</span>attrs<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'course'</span><span class="token punctuation">)</span>
        total_price<span class="token operator">=</span><span class="token number">0</span>
        <span class="token keyword">for</span> course <span class="token keyword">in</span> course_list<span class="token punctuation">:</span>
            total_price<span class="token operator">+=</span>course<span class="token punctuation">.</span>price
        <span class="token keyword">if</span> total_price<span class="token operator">!=</span>total_amount<span class="token punctuation">:</span>
            <span class="token keyword">raise</span> ValidationError<span class="token punctuation">(</span><span class="token string">'价格不合法'</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> total_amount

    <span class="token keyword">def</span> <span class="token function">_gen_out_trade_no</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">import</span> uuid
        <span class="token keyword">return</span> str<span class="token punctuation">(</span>uuid<span class="token punctuation">.</span>uuid4<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span>replace<span class="token punctuation">(</span><span class="token string">'-'</span><span class="token punctuation">,</span><span class="token string">''</span><span class="token punctuation">)</span>

    <span class="token keyword">def</span> <span class="token function">_get_user</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token comment" spellcheck="true"># 需要request对象(需要视图通过context把reuqest对象传入。重写create方法)</span>
        request<span class="token operator">=</span>self<span class="token punctuation">.</span>context<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'request'</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> request<span class="token punctuation">.</span>user

    <span class="token keyword">def</span> <span class="token function">_gen_pay_url</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>out_trade_no<span class="token punctuation">,</span>total_amout<span class="token punctuation">,</span>subject<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token comment" spellcheck="true"># total_amout是Decimal类型，识别不了，需要转换成float类型</span>
        <span class="token keyword">from</span> luffyapi<span class="token punctuation">.</span>libs<span class="token punctuation">.</span>al_pay <span class="token keyword">import</span> alipay<span class="token punctuation">,</span>gateway
        order_string <span class="token operator">=</span> alipay<span class="token punctuation">.</span>api_alipay_trade_page_pay    <span class="token punctuation">(</span>
            out_trade_no<span class="token operator">=</span>out_trade_no<span class="token punctuation">,</span>
            total_amount<span class="token operator">=</span>float<span class="token punctuation">(</span>total_amout<span class="token punctuation">)</span><span class="token punctuation">,</span>
            subject<span class="token operator">=</span>subject<span class="token punctuation">,</span>
            return_url<span class="token operator">=</span>settings<span class="token punctuation">.</span>RETURN_URL<span class="token punctuation">,</span>  <span class="token comment" spellcheck="true"># get回调，前台地址（最后跳转的支付成功页面）</span>
            notify_url<span class="token operator">=</span>settings<span class="token punctuation">.</span>NOTIFY_URL   <span class="token comment" spellcheck="true"># post回调，后台地址（给后端去判断是否支付成功，支付成功返回success）</span>
        <span class="token punctuation">)</span>
        <span class="token keyword">return</span> gateway<span class="token operator">+</span>order_string

    <span class="token keyword">def</span> <span class="token function">_before_create</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>attrs<span class="token punctuation">,</span>user<span class="token punctuation">,</span>pay_url<span class="token punctuation">,</span>out_trade_no<span class="token punctuation">)</span><span class="token punctuation">:</span>
        attrs<span class="token punctuation">[</span><span class="token string">'user'</span><span class="token punctuation">]</span><span class="token operator">=</span>user
        attrs<span class="token punctuation">[</span><span class="token string">'out_trade_no'</span><span class="token punctuation">]</span><span class="token operator">=</span>out_trade_no

        self<span class="token punctuation">.</span>context<span class="token punctuation">[</span><span class="token string">'pay_url'</span><span class="token punctuation">]</span><span class="token operator">=</span>pay_url

    <span class="token keyword">def</span> <span class="token function">validate</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> attrs<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">'''
        # 1）订单总价校验
        # 2）生成订单号
        # 3）支付用户：request.user
        # 4）支付链接生成
        # 5）入库(两个表)的信息准备
        '''</span>
        <span class="token comment" spellcheck="true"># 1）订单总价校验</span>
        total_amout <span class="token operator">=</span> self<span class="token punctuation">.</span>_check_price<span class="token punctuation">(</span>attrs<span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 2）生成订单号</span>
        out_trade_no<span class="token operator">=</span>self<span class="token punctuation">.</span>_gen_out_trade_no<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 3）支付用户：request.user</span>
        user<span class="token operator">=</span>self<span class="token punctuation">.</span>_get_user<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 4）支付链接生成</span>
        pay_url<span class="token operator">=</span>self<span class="token punctuation">.</span>_gen_pay_url<span class="token punctuation">(</span>out_trade_no<span class="token punctuation">,</span>total_amout<span class="token punctuation">,</span>attrs<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'subject'</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 5）入库(两个表)的信息准备</span>
        self<span class="token punctuation">.</span>_before_create<span class="token punctuation">(</span>attrs<span class="token punctuation">,</span>user<span class="token punctuation">,</span>pay_url<span class="token punctuation">,</span>out_trade_no<span class="token punctuation">)</span>
        <span class="token keyword">return</span> attrs
    <span class="token keyword">def</span> <span class="token function">create</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> validated_data<span class="token punctuation">)</span><span class="token punctuation">:</span>
        course_list<span class="token operator">=</span>validated_data<span class="token punctuation">.</span>pop<span class="token punctuation">(</span><span class="token string">'course'</span><span class="token punctuation">)</span>
        order<span class="token operator">=</span>models<span class="token punctuation">.</span>Order<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>create<span class="token punctuation">(</span><span class="token operator">**</span>validated_data<span class="token punctuation">)</span>
        <span class="token keyword">for</span> course <span class="token keyword">in</span> course_list<span class="token punctuation">:</span>
            models<span class="token punctuation">.</span>OrderDetail<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>create<span class="token punctuation">(</span>order<span class="token operator">=</span>order<span class="token punctuation">,</span>course<span class="token operator">=</span>course<span class="token punctuation">,</span>price<span class="token operator">=</span>course<span class="token punctuation">.</span>price<span class="token punctuation">,</span>real_price<span class="token operator">=</span>course<span class="token punctuation">.</span>price<span class="token punctuation">)</span>

        <span class="token keyword">return</span> order</code></pre>
<p>支付成功后，前端会直接跳转到支付成功的页面，支付宝会向后端发送post请求，让我们验证所有的信息是否正确</p>
<pre class=" language-python"><code class="language-python"> <span class="token keyword">def</span> <span class="token function">post</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>request<span class="token punctuation">,</span><span class="token operator">*</span>args<span class="token punctuation">,</span><span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token triple-quoted-string string">'''
        支付宝回调接口
        '''</span>
        <span class="token keyword">from</span> luffyapi<span class="token punctuation">.</span>libs<span class="token punctuation">.</span>al_pay <span class="token keyword">import</span> alipay
        <span class="token keyword">from</span> luffyapi<span class="token punctuation">.</span>utils<span class="token punctuation">.</span>logger <span class="token keyword">import</span> log
        data <span class="token operator">=</span> request<span class="token punctuation">.</span>data
        out_trade_no<span class="token operator">=</span>data<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'out_trade_no'</span><span class="token punctuation">,</span>None<span class="token punctuation">)</span>
        gmt_payment<span class="token operator">=</span>data<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'gmt_payment'</span><span class="token punctuation">,</span>None<span class="token punctuation">)</span>
        signature <span class="token operator">=</span> data<span class="token punctuation">.</span>pop<span class="token punctuation">(</span><span class="token string">"sign"</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 验证签名</span>
        success <span class="token operator">=</span> alipay<span class="token punctuation">.</span>verify<span class="token punctuation">(</span>data<span class="token punctuation">,</span> signature<span class="token punctuation">)</span>
        <span class="token keyword">if</span> success <span class="token operator">and</span> data<span class="token punctuation">[</span><span class="token string">"trade_status"</span><span class="token punctuation">]</span> <span class="token keyword">in</span> <span class="token punctuation">(</span><span class="token string">"TRADE_SUCCESS"</span><span class="token punctuation">,</span> <span class="token string">"TRADE_FINISHED"</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
            models<span class="token punctuation">.</span>Order<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>filter<span class="token punctuation">(</span>out_trade_no<span class="token operator">=</span>out_trade_no<span class="token punctuation">)</span><span class="token punctuation">.</span>update<span class="token punctuation">(</span>order_status<span class="token operator">=</span><span class="token number">1</span><span class="token punctuation">,</span>pay_time<span class="token operator">=</span>gmt_payment<span class="token punctuation">)</span>
            log<span class="token punctuation">.</span>info<span class="token punctuation">(</span><span class="token string">'%s订单支付成功'</span><span class="token operator">%</span>out_trade_no<span class="token punctuation">)</span>
            <span class="token keyword">return</span> Response<span class="token punctuation">(</span><span class="token string">'success'</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            log<span class="token punctuation">.</span>info<span class="token punctuation">(</span><span class="token string">'%s订单有问题'</span> <span class="token operator">%</span> out_trade_no<span class="token punctuation">)</span>
            <span class="token keyword">return</span> Response<span class="token punctuation">(</span><span class="token string">'error'</span><span class="token punctuation">)</span></code></pre>
<p>前端到了支付成功的页面，其实也不完全是支付成功，因为还没有得到后端的确认，所以可以发送一个get请求去校验一下是否成功</p>
<pre class=" language-python"><code class="language-python">    <span class="token keyword">def</span> <span class="token function">get</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span>request<span class="token punctuation">,</span><span class="token operator">*</span>args<span class="token punctuation">,</span><span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span>
        out_trade_no<span class="token operator">=</span>request<span class="token punctuation">.</span>query_params<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'out_trade_no'</span><span class="token punctuation">)</span>
        order<span class="token operator">=</span>models<span class="token punctuation">.</span>Order<span class="token punctuation">.</span>objects<span class="token punctuation">.</span>filter<span class="token punctuation">(</span>out_trade_no<span class="token operator">=</span>out_trade_no<span class="token punctuation">)</span><span class="token punctuation">.</span>first<span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> order<span class="token punctuation">.</span>order_status<span class="token operator">==</span><span class="token number">1</span><span class="token punctuation">:</span>
            <span class="token keyword">return</span> Response<span class="token punctuation">(</span><span class="token boolean">True</span><span class="token punctuation">)</span>
        <span class="token keyword">else</span><span class="token punctuation">:</span>
            <span class="token keyword">return</span> Response<span class="token punctuation">(</span><span class="token boolean">False</span><span class="token punctuation">)</span></code></pre>
</div><div id="reward-container"><span class="hty-icon-button button-glow" id="reward-button" title="打赏" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === &quot;none&quot;) ? &quot;block&quot; : &quot;none&quot;;"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-hand-coin-line"></use></svg></span><div id="reward-comment">点我就给你看点有意思的</div><div id="qr" style="display:none;"><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png" alt="支付宝" title="支付宝"></a><div><span style="color:#00A3EE"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-alipay-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg" alt="QQ 支付" title="QQ 支付"></a><div><span style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg" alt="微信支付" title="微信支付"></a><div><span style="color:#2DC100"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-wechat-pay-line"></use></svg></span></div></div></div></div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者：</strong>爱肖彤真是太好了</li><li class="post-copyright-link"><strong>本文链接：</strong><a href="http://huang_zhao.gitee.io/task/2020/04/25/python/%E6%A8%A1%E5%9D%97/%E6%94%AF%E4%BB%98%E5%AE%9D%E7%BD%91%E9%A1%B5%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8/" title="支付宝网页支付接口调用">http://huang_zhao.gitee.io/task/2020/04/25/python/%E6%A8%A1%E5%9D%97/%E6%94%AF%E4%BB%98%E5%AE%9D%E7%BD%91%E9%A1%B5%E6%94%AF%E4%BB%98%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8/</a></li><li class="post-copyright-license"><strong>版权声明：</strong>本博客所有文章除特别声明外，均默认采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener" title="CC BY-NC-SA 4.0 "><svg class="icon"><use xlink:href="#icon-creative-commons-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-by-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-nc-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-sa-line"></use></svg></a> 许可协议。</li></ul></section></article><div class="post-nav"><div class="post-nav-item"><a class="post-nav-prev" href="/task/2020/04/25/python/%E7%88%AC%E8%99%AB/Xpath%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95/" rel="prev" title="Xpath基本用法"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-left-s-line"></use></svg><span class="post-nav-text">Xpath基本用法</span></a></div><div class="post-nav-item"><a class="post-nav-next" href="/task/2020/04/25/python/%E6%A8%A1%E5%9D%97/celery/" rel="next" title="celery基础"><span class="post-nav-text">celery基础</span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-right-s-line"></use></svg></a></div></div></div></main><footer class="sidebar-translate" id="footer"><div class="copyright"><span>&copy; 2019 – 2022 </span><span class="with-love" id="animate"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-cloud-line"></use></svg></span><span class="author"> 爱肖彤真是太好了</span></div><div class="powered"><span>由 <a href="https://hexo.io" target="_blank" rel="noopener">Hexo</a> 驱动 v5.1.1</span><span class="footer-separator">|</span><span>主题 - <a rel="noopener" href="https://github.com/YunYouJun/hexo-theme-yun" target="_blank"><span>Yun</span></a> v0.9.7</span></div><div class="live_time"><span>本博客已萌萌哒地运行</span><span id="display_live_time"></span><span class="moe-text">(●'◡'●)</span><script>function blog_live_time() {
  window.setTimeout(blog_live_time, 1000);
  const start = new Date('2019-04-12T00:00:00');
  const now = new Date();
  const timeDiff = (now.getTime() - start.getTime());
  const msPerMinute = 60 * 1000;
  const msPerHour = 60 * msPerMinute;
  const msPerDay = 24 * msPerHour;
  const passDay = Math.floor(timeDiff / msPerDay);
  const passHour = Math.floor((timeDiff % msPerDay) / 60 / 60 / 1000);
  const passMinute = Math.floor((timeDiff % msPerHour) / 60 / 1000);
  const passSecond = Math.floor((timeDiff % msPerMinute) / 1000);
  display_live_time.innerHTML = " " + passDay + " 天 " + passHour + " 小时 " + passMinute + " 分 " + passSecond + " 秒";
}
blog_live_time();
</script></div><div id="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_site_uv" title="总访客量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-user-line"></use></svg></span><span id="busuanzi_value_site_uv"></span></span><span class="footer-separator">|</span><span id="busuanzi_container_site_pv" title="总访问量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg></span><span id="busuanzi_value_site_pv"></span></span></div></footer><a class="hty-icon-button" id="goUp" aria-label="back-to-top" href="#"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-up-s-line"></use></svg><svg class="progress-circle-container" viewBox="0 0 100 100"><circle class="progress-circle" id="progressCircle" cx="50" cy="50" r="48" fill="none" stroke="#0078E7" stroke-width="2" stroke-linecap="round"></circle></svg></a><a class="popup-trigger hty-icon-button icon-search" id="search" href="javascript:;" title="搜索"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search-line"></use></svg></span></a><script>window.addEventListener("DOMContentLoaded", () => {
  // Handle and trigger popup window
  document.querySelector(".popup-trigger").addEventListener("click", () => {
    document.querySelector(".popup").classList.add("show");
    setTimeout(() => {
      document.querySelector(".search-input").focus();
    }, 100);
  });

  // Monitor main search box
  const onPopupClose = () => {
    document.querySelector(".popup").classList.remove("show");
  };

  document.querySelector(".popup-btn-close").addEventListener("click", () => {
    onPopupClose();
  });

  window.addEventListener("keyup", event => {
    if (event.key === "Escape") {
      onPopupClose();
    }
  });
});
</script><script src="/task/js/search/local-search.js" defer></script><div class="popup search-popup"><div class="search-header"><span class="popup-btn-close close-icon hty-icon-button"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-close-line"></use></svg></span></div><div class="search-input-container"><input class="search-input" id="local-search-input" type="text" placeholder="搜索..." value=""></div><div id="local-search-result"></div></div></div><script defer src="/task/js/utils.js"></script><script defer src="/task/js/hexo-theme-yun.js"></script></body></html>